//
//  ILGMultiThreadModule.m
//  ILGDemo
//
//  Created by happy on 2020/4/2.
//  Copyright © 2020 Happy. All rights reserved.
//

#import "ILGMultiThreadModule.h"
#import "ILGCustomOperation.h"

#ifndef dispatch_queue_async_safe
#define dispatch_queue_async_safe(queue, block)\
    if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(queue)) == 0) {\
        block();\
    } else {\
        dispatch_async(queue, block);\
    }
#endif

@interface ILGMultiThreadModule ()
@property (nonatomic, assign) NSInteger ticketSurplusCount;
@property (nonatomic, strong) NSLock *lock;
@property (nonatomic, strong) ILGCustomOperation *operation;
@end

@implementation ILGMultiThreadModule

- (void)performTestMethod
{
    NSLog(@"%s", __func__);
//    [self testingCode];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"dispatch_async(dispatch_get_main_queue()");
    });
    
    
    /*
    dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.app.ilgDemo.ILGMultiThreadModuleQueue", NULL);
    dispatch_async(mySerialDispatchQueue, ^{
        [self testGCD:mySerialDispatchQueue];
    });
     */
}

- (void)testGCD:(dispatch_queue_t)serialDispatchQueue
{
    const char *currentLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
    const char *myLabel = dispatch_queue_get_label(serialDispatchQueue);
    
    if (strcmp(currentLabel, myLabel) == 0) {
        NSLog(@"%s", __func__);
    } else {
        dispatch_sync(serialDispatchQueue, ^{
            NSLog(@"%s", __func__);
        });
    }
}

- (void)dealloc
{
    NSLog(@"%s", __func__);
    [_operation removeObserver:self forKeyPath:@"isExecuting"];
}


#pragma mark - NSOperationQueue

- (void)oq_testingCodeOne
{
    [self testingCodeOne];
}

- (void)op_testingForBlockOperation
{
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"blockOperation 1 ended, %@", [NSThread currentThread]);
    }];
    
    [blockOperation addExecutionBlock:^{
        NSLog(@"blockOperation 2 ended, %@", [NSThread currentThread]);
    }];

    [blockOperation addExecutionBlock:^{
        NSLog(@"blockOperation 3 ended, %@", [NSThread currentThread]);
    }];
    
    [blockOperation setCompletionBlock:^{
        NSLog(@"blockOperation ended");
    }];
    
    [blockOperation start];
}

- (void)op_testingForKVO
{
    NSOperationQueue *myQueue = [[NSOperationQueue alloc] init];
    myQueue.maxConcurrentOperationCount = 1;
    
    NSOperationQueue *yourQueue = [[NSOperationQueue alloc] init];

    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block operation 1, %@", [NSThread currentThread]);
    }];
    
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block operation 2, %@", [NSThread currentThread]);
    }];
    
    ILGCustomOperation *operation3 = [[ILGCustomOperation alloc] init];
    operation3.queuePriority = NSOperationQueuePriorityVeryHigh;
    
    self.operation = operation3;
    [operation3 addObserver:self forKeyPath:@"isExecuting" options:NSKeyValueObservingOptionNew context:nil];
//    [operation addDependency:operation2];
    
    [myQueue addOperation:operation];
    [myQueue addOperation:operation2];
    [myQueue addOperation:operation3];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"observeValueForKeyPath %@, %@", change, [NSThread currentThread]);
}


#pragma mark - GCD

static NSLock *lock;
- (void)testingCodeOne
{
    lock = [[NSLock alloc] init];
            
    dispatch_queue_t serialQueue = dispatch_queue_create("com.app.Demo.testQueue", DISPATCH_QUEUE_CONCURRENT);
    
    for (int index = 0; index < 1; index++) {
        dispatch_async(serialQueue, ^{
            if (index == 2) {
                [lock lock];
            }
            NSLog(@"com.app.ilgDemo.testQueue ended %d, %@", index, [NSThread currentThread]);
        });
    }
    
    dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.app.ilgDemo.ILGMultiThreadModuleQueue", NULL);
    dispatch_queue_t globalDispatchQueueBackground = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
    dispatch_set_target_queue(mySerialDispatchQueue, globalDispatchQueueBackground);
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
    });
    
    char *str = "serialQueue释放啦";
    dispatch_set_context(serialQueue, str);
    dispatch_set_finalizer_f(serialQueue, &queuecallback);
}

void queuecallback(void *context)
{
    NSLog(@"callback %s", context);
}

- (void)testingCodeForDispatchGroup {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"block1");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"block2");
    });
    dispatch_group_async(group, queue, ^{
        NSLog(@"block3");
    });
    
    dispatch_group_notify(group, queue, ^{
        NSLog(@"group done");
    });
    
    
    // 指定等待间隔为1秒：
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC);
    long result = dispatch_group_wait(group, time);
    if (result == 0) {
        // group中的任务全部执行结束
    } else {
        
    }
    
    
    // 不用任何等待即可判定属于Dispatch Group的处理是否执行结束
    long result2 = dispatch_group_wait(group, DISPATCH_TIME_NOW);
}

- (void)testingCodeForDispatchBarrierAsync {
    dispatch_queue_t queue = dispatch_queue_create("com.app.ilgDemo.ForBarrier", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(queue, ^{ NSLog(@"reading something 1"); });
    dispatch_async(queue, ^{ NSLog(@"reading something 2"); });
    dispatch_async(queue, ^{ NSLog(@"reading something 3"); });
    dispatch_barrier_async(queue, ^{ NSLog(@"writing something 1"); });
    NSLog(@"after dispatch_barrier_async");
    dispatch_async(queue, ^{ NSLog(@"reading something 4"); });
    dispatch_async(queue, ^{ NSLog(@"reading something 5");});
}

static dispatch_once_t onceToken;
static ILGMultiThreadModule *instance = nil;
+ (instancetype)sharedInstance
{
    dispatch_once(&onceToken, ^{
        instance = [[ILGMultiThreadModule alloc] init];
        NSLog(@"%s", __func__);
    });
    return instance;
}

- (void)destorySharedInstance
{
    onceToken = 0;
    instance = nil;
}

- (void)testingCode {
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t myQueue = dispatch_queue_create("com.app.ilgDemo.muQueue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; i++) {
        dispatch_group_enter(group);
//        dispatch_group_async(group, queue, ^{
            dispatch_async(myQueue, ^{
                NSLog(@"dispatch_async %d ended", i);
                dispatch_group_leave(group);
//                dispatch_group_leave(group);
            });
//        });
    }
    
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    NSLog(@"dispatch_group_notify ended");
    
//    dispatch_group_notify(group, queue, ^{
//        NSLog(@"dispatch_group_notify ended");
//    });
    
    /*
    NSArray *array = [NSArray arrayWithObjects:@"1", @"2",@"3",@"4",@"5",nil];
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        dispatch_apply([array count], queue, ^(size_t index) {
            NSLog(@"%zu: %@", index, [array objectAtIndex:index]);
        });
        
        dispatch_async(dispatch_get_main_queue(), ^{
            // 通知用户界面更新
        });
    });
     */
}

- (void)testingCodeForDeadLock {
//    dispatch_queue_t queue = dispatch_get_main_queue();
//    dispatch_sync(queue, ^{
//        NSLog(@"能不死锁吗？不能");
//    });
    
    
//    dispatch_queue_t queue = dispatch_get_main_queue();
//    dispatch_async(queue, ^{
//        dispatch_sync(queue, ^{
//            NSLog(@"能不死锁吗？不能");
//        });
//    });
    
//    dispatch_queue_t queue = dispatch_queue_create("com.app.ilgDemo.MySerialDispatchQueue", NULL);
//    dispatch_async(queue, ^{
//        dispatch_sync(queue, ^{
//            NSLog(@"能不死锁吗？不能");
//        });
//    });
}

@end
